<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // function fn(){

        // }
        // console.dir(fn);

        //   function fn(){
        //     let obj = {};
        //   }
        //  let f =  fn();

        // 堆内存  栈内存

        // 只要当前的堆内存不被占用了

        // let obj = {};
        // let s = obj;
        // obj = null; // 解除关联
        // s = null;

        // 全局栈内存
        //  let a = 12;

        //    function fn(){
        //      let a = 13; // {}
        //      return a;
        //    }
        //  let f =  fn();
        // 在当前私有栈内存中开辟一个引用值，并且被外界多接收(占用)，那当前的作用域就不销毁

        // 私有的栈内存
        // 销毁
        // 

        // function fn() {
        //   /* 
        //     a = 10 11 12
        //    */
        //   let a = 10;
        //   return function () { // af0
        //     /* 

        //      */
        //     console.log(a++);
        //   }
        // }

        // let f = fn(); // af0
        // // 函数执行形成一个不销毁的作用域，他可以保存里边的变量不收外界干扰,还可以保存里边的变量一直存在，这种保护和保存的机制就是闭包机制

        // f(); // 10
        // f(); // 11


        // function fn(){
        //   let a = 10;
        //   return function(){

        //       console.log(a++);
        //   }
        // }
        // fn()() // 先让fn执行，然后把fn的执行结果加上小括号继续执行
        // af0()

        // let f = fn()();
        // console.log(f);


        /* 
        f = af0 af3
        g = af1
         */
        // f = function () { return true; } // af0
        // g = function () { return false; } // af1

        // ~function () {
        //   /* 
        //   g = af2
        //    */

        //   if (g || [] == ![]) { // 对象 == 布尔  0 ==  0  true
        //     // 新版本浏览器中带fnunction只声明不定义
        //     // if条件一旦成立之后所做的第一件事就是给函数名赋值
        //     f = function () { return false; } // af3
        //     function g() { return true; } // af2
        //   }
        // }();
        // console.log(f()); // false
        // console.log(g()); // false


        /* 
        n = 20 21 22 24
        outer = af0
         */
        // var n = 20;
        // function outer() { // af0
        //     /* 
        //     inner = af1
        //      */
        //     ++n;
        //     function inner() { // af1
        //         /* 
        //         center = af2
        //          */
        //         console.log(n++); // 21
        //         function center() { // af2
        //             /* 

        //              */
        //             n += 2;
        //             console.log(n); // 24
        //         }
        //         center();
        //     }
        //     inner();
        // };
        // outer();
        // console.log(n) // 24

        //--------------------------------------------------------

        /* 
        i = 2 4 3 2 4 3
        fn = af0
        f = af1
         */
        // var i = 2;
        // function fn() {
        //     /* 
        //      // 此作用域不销毁
        //      */
        //     i += 2;
        //     return function (n) { // af1
        //         /* 
        //         n = 3
        //          */
        //         console.log(n + (--i)); // 3 + 2
        //     }
        // }
        // var f = fn(); // af1
        // f(); // NaN
        // f(3); // 5
        // fn()(2); // af2()   5



        // function fn() {
        //     /* 

        //      */
        //     i += 2;
        //     return function (n) { // af2
        //         /* 
        //         n = 2
        //          */
        //         console.log(n + (--i)); // 2 + 3
        //     }
        // }

        //----------------------------------------------------

        /* 
        a = 9 0 1 0 1 2
        fn = af0
        f = af1
        m = 5
        n = 5
        x = 6
         */
        // var a = 9;
        // function fn() {
        //     /* 
        //     此作用域不销毁
        //      */
        //     a = 0;
        //     return function (b) { // af1
        //         /* 
        //         b = 5
        //         销毁
        //          */
        //         return b + a++; // 5 +1-->6
        //     }
        // }
        // var f = fn();
        // var m = f(5); // 5
        // alert(m); // '5'

        // var n = fn()(5); // af2()
        // alert(n); // '5'

        // var x = f(5); // 6
        // alert(x); // '6'
        // alert(a); // '2'



        // function fn() {
        //     /* 
        //     此作用域不立即销毁
        //      */
        //     a = 0;
        //     return function (b) { // af2
        //         /* 
        //         b = 5  销毁
        //          */
        //         return b + a++; // 5 + 0 -->5
        //     }
        // }

        //---------------------------------------------------



        // 全局作用域下的this是window
        // 函数里的this，要看函数执行前有没有点，如果有点，那点前面是谁，函数里的this就是谁，如果没有点，那函数里的this就是window
        // 自执行函数里的this是window

        // 回调函数里的this一把情况下也是window
        // 给当前元素的事件行为绑定方法，那方法里的this就是当前元素本身

        // function fn(f){
        //     // console.log(f); // 1
        //     f()
        // }
        // fn(function(){
        //     console.log(this);
        // })

        // setTimeout(function(){
        //     console.log(this);
        // },1000);

        // let ary = [100,200,300,400];
        // ary.forEach(function(item,index){
        //     console.log(this);
        // })


        /* 
        a = 1 1 3
        obj1 = af0
        fn1 = af1
        
         */
        // var a = 1;
        // var obj1 = { // af0
        //     a: 0, // 2
        //     fn1: (function (a) {
        //             /* 
        //             a = 1 2 3 4
        //             此作用域不销毁
        //              */
        //             this.a = a; // window.a = 1
        //             a++;
        //             return function () { // af1
        //                 /* 

        //                  */
        //                 this.a = a++;
        //                 // window.a = a++  3
        //                 console.log(a); // 4
        //         }
        //     })(a) // 1
        // };
        // obj1.fn1(); // 3  this-->obj1
        // var fn1 = obj1.fn1;
        // fn1(); // 4   this-->window
        // console.log(a); // 3
        // console.log(obj1.a); // 2

        //------------------------------------------

        /* 
        num = 1 2 4
        obj = af0
        f = af0
         */
        // var num = 1;
        // var obj = {
        //     num: 2, // 4
        //     fn: (function (num) {
        //             /* 
        //             num = 1 4 1 3 4 6 7
        //             不销毁
        //              */
        //         this.num *= 2; // window.num*=2
        //         num += 3;
        //         var num = 1;
        //         return function () { // af0
        //            /* 

        //             */
        //             num += 2;
        //             this.num += 2; //obj.num+=2
        //             console.log(++num); // 7
        //         }
        //     })(num)
        // };
        // var f = obj.fn;
        // f(); // 4  this-->window
        // obj.fn(); // 7  this-->obj
        // console.log(window.num, obj.num); // 4 4

        //-------------------------------------------------

        /* 
        number = 2 4 8
        obj = af0
        fn1 = af1
         */
        var number = 2;
        var obj = { // af0
            number: 4, // 8
            fn1: (function () {
                    /* 
                    number = NaN 3 9 27
                     */
                    this.number *= 2; // window.number*=2
                    number = number * 2; // undefined*2
                    var number = 3;
                    return function () { // af1
                        /* 
                        
                         */
                        this.number *= 2;  // obj.number*=2
                        number *= 3;
                        alert(number); // '27'
                    }
            })()
        };
        var fn1 = obj.fn1;
        alert(number); // '4'
        fn1(); // '9' this-->window
        obj.fn1(); // '27' this-->obj
        alert(window.number); // '8'
        alert(obj.number); // '8'


    </script>
</body>

</html>